home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 1997
/
MacHack 1997.toast
/
Hacks
/
Hacks ’93
/
Mystery Science Mac
/
INIT sources
/
ShowINIT.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-08-24
|
14KB
|
452 lines
#include "MacHeaders7"
#include "Utils.h"
#include "MSM.h"
#define using_MacTraps 1
#if 0
; File: ShowINIT.a
; Last Modified: Sunday, November 26, 1989 05:07:56 PM
;------------------------------------------------------------------------------------------------
;
; INIT notification routine
; by Paul Mercer, Darin Adler, Paul Snively and Frédéric Miserey from an idea by Steve Capps
;
; Created: 6/7/87 PM - First version.
; Modified: 6/15/87 PM - Changed to standard (Pascal) calling conventions.
; 6/20/87 PM - Fixed color & Finder bug on Mac II.
; 6/22/87 DBA - Improved handling of QuickDraw.
; 6/29/87 DBA - Used scratch8 to avoid conflict with “Easy Access”.
; 6/30/87 DBA - Changed to a 4-byte scheme with “checksum”.
; 6/30/87 PFS - Separated into ShowINIT and InnerShowINIT.
; 7/1/87 DBA - Fixed stack bug and switched to CurApName+.
; 7/2/87 PM - Added check for old signature in ApplScratch for
; backword compatibility (TMON Startup).
; 7/3/87 PM - Removed _SysBeep in ErrorExit since it causes a crash.
; Also changed ICN# plotter to srcOr mode for Blinker.
; 7/13/87 PM - Fixed a3 trashing bug in InnerShowINIT - exit code left
; word on stack (reported by D. Dunham).
; 7/21/87 PM - Due to popular demand, InitGraf is no longer being called.
; This avoids the gamma correction problem with Startupscreens
; getting “washed out” by ShowINIT though someone else is still
; bound to call InitGraf sooner or later (i.e. InitWindows).
; 7/29/87 PM - Put InitGraf back in; this is required (reported by C. Derossi
; at Apple Tech Support). Took out GetPort/SetPort.
; 10/06/87 PM - Set CurrentA5 properly. Rearranged myVars.
; 12/28/87 PM - Major revision to accomodate future INIT31 based ShowINIT.
; 07/14/88 PM - Major revision to get rid of above 'accomodations'.
; Added color icon 'cicn' support and fixed beep crash.
; Removed support for old signature.
; 11/25/89 FCM - Added Y dimension support, icl48 support to get rid of 'obsolete' cicns
; 8/28/90 jbx - Translated to Think C, added automatic x-movement determination.
; Removed support for 'obsolete' cicn’s.
;
;------------------------------------------------------------------------------------------------
#endif
/* Originally written by Paul Mercer. Translated to Think C by jbx. */
typedef struct {
long Icon[32];
long IconMask[32];
} ICONList, *ICONListPtr;
extern short myVCheck : 0x928; /* a GREAT place to store 8 bytes (it was Darin's idea) */
extern short myV : 0x92A;
extern short myH : 0x92C;
extern short myHCheck : 0x92E; /* a simple checksum of myH to determine first-timeness */
enum {
firstX = 8, /* X coordinate of first icon to be drawn */
bottomEdge = 8+32, /* this far from bottom of screen */
iconWidth = 32, /* size of icon (square normally) */
defaultMoveX = 40, /* x default amount to move icons */
defaultMoveY = 40, /* y icon line height */
checksumConst = 0x1021, /* constant used for computing checksum */
iconRowBytes = 32/8, /* 32/8 bits */
hasCQDBit = 6, /* this bit in ROM85 is cleared if Color QuickDraw is available */
iconID = 6+4, /* positive stackframe objects */
moveX = 4+4, /* horizontal distance between ShowINIT icons. */
showINITArgs = 4,
iconPtr = 6+4,
initDrawArgs = 6,
iclPtrHdl = 12+4,
iclDepth = 10+4,
initDrawXArgs = initDrawArgs+6
};
#ifndef using_MacTraps
static struct {
char qd_privates[76]; /* known only to Apple and MacWEEK... */
long qd_randSeed;
BitMap qd_screenBits;
Cursor qd_arrow;
Pattern qd_dkGray;
Pattern qd_ltGray;
Pattern qd_gray;
Pattern qd_black;
Pattern qd_white;
GrafPtr qd_thePort;
} qd;
#define thePort qd.qd_thePort
#define white qd.qd_white
#define black qd.qd_black
#define gray qd.qd_gray
#define ltGray qd.qd_ltGray
#define dkGray qd.qd_dkGray
#define arrow qd.qd_arrow
#define screenBits qd.qd_screenBits
#define randSeed qd.qd_randSeed
#endif
static long saveA5;
static long localA5;
static Rect srcRect = {0,0,32,32}; /* for copybits */
static Rect destRect= {0,0,32,32};
static BitMap myBitMap = {
0, /* address */
iconRowBytes, /* rowBytes */
0,0,32,32 /* Rect */
};
static BitMap myMaskMap = {
0, /* address */
iconRowBytes, /* rowBytes */
0,0,32,32 /* Rect */
};
static GrafPort myPort;
static pascal void INITDraw1Bit(ICONListPtr iconPtr);
static pascal void INITDrawCQD(CIconHandle);
static pascal void INITDrawXBit(void *icl_Ptr, short iclDepth, ICONListPtr iconPtr);
/***************************************************************************************\
| |
| Displays the ICN# (cicn when in 4 bit mode or higher) specified by iconID. |
| |
| PROCEDURE ShowINIT(iconID: Integer); EXTERNAL; |
| |
| pascal void ShowINIT(short iconID); |
| extern; |
| |
\***************************************************************************************/
pascal void ShowINIT(short iconID) {
register void *Addr3, *Addr2;
register long Data7, Data6, Data5, Data4, Data3;
asm {
ShowINIT:
btst.b #hasCQDBit,ROM85 ; try to get a color icon if CQD exists
beq @ShowINITCQD ; I could use SysEnvirons but I don't want to
ShowINIT1Bit:
clr.l -(sp) ; try to get the icon resource
move.l #'ICN#',-(sp)
move.w iconID(a6),-(sp)
GetResource
move.l (sp)+,d0
beq @ShowINITError ; can't get it, give up
move.l d0,-(sp) ; leave handle on the stack for ReleaseResource
move.l d0,a0
HLock
move.l (a0),a0 ; dereference
move.l a0,-(sp) ; icon pointer
jsr INITDraw1Bit ; draw
ReleaseResource ; release the resource
return
ShowINITCQD:
move.l #0x40008,d2
move.l #'icl8',d3
move.l #'icl4',d4
move.l MainDevice,a0 ; get handle to main device
move.l (a0),a0 ; dereference
move.l OFFSET(GDevice, gdPMap)(a0),a0
; get its pixmap handle
move.l (a0),a0 ; dereference it
cmpi.w #4,OFFSET(PixMap,pixelSize)(a0)
; is it deep enough for us to draw with icl4?
blt.s @ShowINIT1Bit ; no, go to 1-bit.
; is it deep enough for us to draw with icl8?
beq.s @SwapOrder ; no, swap order.
tryAgain:
clr.l -(sp)
move.l d3,-(sp)
move.w iconID(a6),-(sp)
GetResource
move.l (sp)+,d1
bne.s @FoundIc
clr.w d2
SwapOrder:
swap d2
beq @tryCICN
exg d3,d4
bra.s @tryAgain
tryCICN:
goto ShowINIT1Bit
FoundIc:
clr.l -(sp)
move.l #'ICN#',-(sp)
move.w iconID(a6),-(sp)
GetResource
move.l (sp)+,d0
bne.s @FoundCompanion
move.l d1,-(sp)
ReleaseResource
bra @tryCICN
FoundCompanion:
move.l d1,-(sp) ; leave handle on the stack for ReleaseResource
move.l d0,-(sp) ; leave handle on the stack for ReleaseResource
move.l d0,d3
move.l d1,a0
HLock
move.l (a0),a0 ; dereference
move.l a0,-(sp) ; icl_ pointer
move.w d2,-(sp) ; icl_ depth
move.l d3,a0
HLock
move.l (a0),a0 ; dereference
move.l a0,-(sp) ; icon pointer
jsr INITDrawXBit ; draw
ReleaseResource ; release the resource
ReleaseResource ; release the resource
return
ShowINITError:
move.w #8,-(sp) ; just beep
SysBeep
return
}
}
static void ShowINITCredits(void) {
asm {
dc.b "ShowINIT by Paul Mercer" ,0
dc.b "Copyright 1987-1989" ,0
dc.b "Version of 11/25/89" ,0
dc.b "Modified by jbx 8/28/90" ,0
};
}
/***************************************************************************************\
| |
| Initializes the world and sets up the drawing rectangle |
| |
\***************************************************************************************/
static void INITInit(void) {
asm {
move.l CurrentA5,saveA5 ; PM 10/6 save host A5
lea localA5,a5 ; PM7/21
move.l a5,CurrentA5
pea thePort ; PM 10/6 use a5 reference instead of a6
InitGraf ; fixes color bug as per DA@ICOM
pea myPort
OpenPort
move.w myV,d0 ; get my v var
rol.w #1,d0 ; compare against checksum
eor.w #checksumConst,d0
cmp.w myVCheck,d0
beq.s @ScratchVOK ; checks, so go on test my h var
move.w myPort.portBits.bounds.bottom,d0 ; else initialize as first time
sub.w #bottomEdge,d0
move d0,myV
ScratchVOK:
move.w myH,d0 ; get my h var
rol.w #1,d0 ; compare against checksum
eor.w #checksumConst,d0
cmp.w myHCheck,d0
beq.s @ScratchHOK ; checks, so go on
move #firstX,myH ; else initialize as first time
ScratchHOK:
move.l myV,d0 ; trickery - high word is V, lo word is H.
move.w d0,d1 ; get future position
add.w #iconWidth,d1 ; compute future rect right
cmp.w myPort.portBits.bounds.right,d1 ; compare to main screen right
blt.s @DontChangeLine ; smaller - do nothing
move.w myV,d0 ; decrement Y value
subi.w #defaultMoveY,d0
move.w d0,myV
move.w #firstX,myH ; set X to initial value
move.l myV,d0
DontChangeLine:
lea destRect,a0
move.l d0,(a0)+
move.l d0,(a0)
}
}
/***************************************************************************************\
| |
| Based on the mask, advances the icon drawing position and adjusts destRect |
| |
\***************************************************************************************/
static void MaskAdjust(void) {
asm {
lea myMaskMap,a0
move.l (a0)+,a1 ; baseAddr
move.w (a0)+,d0 ; rowBytes
move.w 4(a0),d1 ; bottom
move.w 6(a0),d2 ; right
sub.w (a0)+,d1 ; top - d1 now has height.
sub.w (a0)+,d2 ; left - d2 now has width.
add.w d1, destRect.bottom
add.w d2, destRect.right
cmpi.w #4,d0 ; is rowBytes 4? Might not be on a color icon!
beq.s @four
add.w d2,myH ; so assume the icon is properly done,
goto done ; without any mask holes.
four:
add.w #32,myH ; assume the icon is normal.
moveq #0,d0 ; d0 accumulates the mask columns.
subq.w #1,d1
bmi.s @out ; oops, no height, we're outa here.
ol: or.l (a1)+,d0
dbra d1, @ol
; OK, now d0's bits correspond to the columns of the mask.
; make sure there really is a mask...
tst.l d0
bne.s @lft
out:return ; and if not, we're outa here!
; first thing, we shift the icon to the left for every empty high bit:
ll: subq.w #1,destRect.left
subq.w #1,destRect.right
asl.l #1,d0
lft:bpl.s @ll
; OK, now the icon is properly positioned. Now we check for empty space on
; on the right, which we can use to properly figure the destination rectangle:
rl: ror.l #1,d0
bmi.s @done
subq.w #1,myH
bra.s @rl
}
done:
myH += 8;
}
/***************************************************************************************\
| |
| Cleans up the work done by INITInit and advances the icon drawing position |
| |
\***************************************************************************************/
static void INITCleanup(void) {
asm {
move.w myH,d0 ; get current position
rol.w #1,d0 ; recompute h checksum
eor.w #checksumConst,d0
move.w d0,myHCheck ; and save it
move myV,d0 ; same for v checksum
rol.w #1,d0
eor.w #checksumConst,d0
move.w d0,myVCheck
pea myPort ; *** (DBA) I think that QuickDraw leaves handles around.
ClosePort ; *** (DBA) Too bad we can't get rid of them...
move.l saveA5,a5 ; PM 10/6 restore host A5
move.l a5,CurrentA5
}
}
/***************************************************************************************\
| |
| display the ICN# pointed to by iconPtr and move the pen horizontally by moveX |
| pass a -1 in moveX to move the standard amount, moveX should be 40 for most ICN#'s |
| |
| PROCEDURE INITDraw1Bit(iconPtr: ICONListPtr); EXTERNAL |
| |
| pascal void INITDraw1Bit(ICONListPtr iconPtr); |
| |
\***************************************************************************************/
static pascal void INITDraw1Bit(ICONListPtr iconPtr) {
INITInit(); /* initialize for drawing. */
myBitMap.baseAddr = (void *)iconPtr->Icon;
myMaskMap.baseAddr = (void *)iconPtr->IconMask;
MaskAdjust();
CopyMask(&myBitMap, &myMaskMap, &myPort.portBits, &srcRect, &srcRect, &destRect);
INITCleanup(); /* cleanup, advance icon location */
}
/***************************************************************************************\
| |
| display the Icl pointed to by iclPtr and move the pen horizontally by moveX |
| pass a -1 in moveX to move the standard amount, moveX should be 40 for most ICN#'s |
| |
| PROCEDURE INITDrawXBit(iclPtr: icl_Ptr; iclDepth: Integer; |
| iconPtr: ICONListPtr); EXTERNAL; |
| |
| pascal void INITDrawXBit(icl_Ptr, iclDepth, moveX) |
| icl_Ptr *iclPtr; |
| short iclDepth; |
| ICONList *iconPtr; |
| extern; |
| |
\***************************************************************************************/
static pascal void INITDrawXBit(void *icl_Ptr, R short iclDepth, ICONListPtr iconPtr) {
PixMapHandle pmh;
R PixMapPtr pmp;
if (!(pmh = NewPixMap())) {
INITDraw1Bit(iconPtr);
} else {
INITInit(); /* initialize for drawing */
HLock(pmh);
pmp = *pmh;
DisposHandle(pmp->pmTable);
pmp->pmTable = (CTabHandle) RGetResource('clut', iclDepth);
pmp->baseAddr = icl_Ptr;
pmp->rowBytes = 0x8000 | (iclDepth * iconRowBytes);
pmp->bounds = srcRect;
pmp->pixelType = chunky;
pmp->pixelSize = iclDepth;
pmp->cmpCount = 1;
pmp->cmpSize = iclDepth;
myMaskMap.baseAddr = (void *)iconPtr->IconMask;
MaskAdjust();
CopyMask(pmp, &myMaskMap, &myPort.portBits, &srcRect, &srcRect, &destRect);
pmp->pmTable = (void *)NewHandle(0);
DisposPixMap(pmh);
INITCleanup(); /* cleanup, advance icon location */
}
}